/* eslint-disable */
import Frame from './Frame';
// import { Base64 } from 'js-base64';
import guid from 'guid';

/**
 * Class containing recorded frames
 */
export default class Movie {

  /**
   * Create movie
   * @param {Object} opts Options
   * @param {Array<Frame|Object>} [opts.frames=[]] Array of frames
   * @param {number} [opts.top=0] Top position of the movie, relative to document
   * @param {number} [opts.left=0] Left position of the movie, relative to document
   * @param {number} [opts.scrollX=0] The initial horizontal scroll position inside player target
   * @param {number} [opts.scrollY=0] The initial vertical scroll position inside player target
   * @param {string} [opts.scene=''] Base64 encoded HTML string
   * @example
   * let frame = new cimice.Frame({eventType: 'click'});
   * let movie = new cimice.Movie({
   *     top: 100,
   *     left: 100,
   *     scene: 'SGFja2VyIERldGVjdGVkIQ==',
   *     frames: [1489
   *       {eventType: 'click'},
   *       frame,
   *       {eventType: 'mousemove'}
   *     ],
   * });
   */
  constructor(opts = {}) {
    this.id = guid.raw();
    this.rootId = opts.rootId || 0;
    this.children = opts.children || [];
    this.base = opts.base || '';
    this.top = opts.top || 0;
    this.left = opts.left || 0;
    this.scrollX = opts.scrollX || 0;
    this.scrollY = opts.scrollY || 0;
    this.duration = 0;
    this.frames = [];
    const frames = opts.frames || [];

    for (let i = 0; i < frames.length; i++) {
      this.addFrame(new Frame(frames[i]));
    }

    this._resetDuration();
  }

  getId(){
    return this.id;
  }

  getRootId() {
    return this.rootId;
  }

  getChildren() {
    return this.children;
  }

  _resetDuration() {
    if (this.frames && this.frames.length > 0) {
      this.duration = this.frames[this.frames.length - 1].ts - this.frames[0].ts;
    }
  }

  /**
   * Add new frame to the collection. If the object passed is an instance of Frame
   * it will added as it is, in case of simple object will create a new Frame
   * and set actual timestamp.
   * @param {Frame|Object} frame Frame instance or object
   * @returns {Frame|undefined} Added frame
   * @example
   * let frame1 = movie.addFrame({eventType: 'click'});
   * // Or
   * let frame = new cimice.Frame({eventType: 'click'});
   * let frame2 = movie.addFrame(frame);
   */
  addFrame(frame = {}) {
    let result;

    if (frame instanceof Frame) {
      result = frame;
    } else if (frame !== null && typeof frame === 'object') {
      result = new Frame(frame);
      const d = new Date();
      result.ts = d.getTime();
    }

    if (result) {
      this.frames.push(result);
    }

    this._resetDuration();

    return result;
  }

  /**
   * Get the collection of frames
   * @returns {Array<Frame>} Array of frames
   */
  getFrames() {
    return this.frames;
  }

  addFrames(frames = []) {
    frames.forEach((frame) => {
      this.addFrame(frame);
    });

    this._resetDuration();
  }

  /**
   * Set a new collection of frames.
   * @param {Frame|Object|Array<Frame|Object>} Array of frames or also a single Frame/object
   * @returns {this}
   * @example
   * let frame = new cimice.Frame({});
   * movie.setFrames(frame);
   * // frames -> 1
   * movie.setFrames([frame, {eventType: 'click'}]);
   * // frames -> 2
   * movie.setFrames({eventType: 'click'});
   * // frames -> 1
   */
  setFrames(frames) {
    const f = [].concat(frames || []);
    this.frames = [];
    for (let i = 0; i < f.length; i++) {
      this.addFrame(f[i]);
    }
    this._resetDuration();
    return this;
  }

  /**
   * Returns movie and related frames in JSON format. Generally coulde be used to extract data
   * during the recording and send back to server
   * @returns {string} JSON data
   * @example
   * let json = JSON.stringify(movie);
   * let xhr = new XMLHttpRequest();
   * xhr.open('POST', url);
   * xhr.send(json);
   */
  toJSON() {
    return {
      top: this.top,
      left: this.left,
      scrollX: this.scrollX,
      scrollY: this.scrollY,
      frames: this.frames,
      base: this.base,
      children: this.children,
      rootId: this.rootId
    };
  }
}
